package com.cloudptt.api.product.func.call.group.fsm.call;

import com.cloudptt.api.comm.CauseCont;
import com.cloudptt.api.comm.CommDlg;
import com.cloudptt.api.comm.Common;
import com.cloudptt.api.models.call.RtcpMsg;
import com.cloudptt.api.pjsip.api.SipManager;
import com.cloudptt.api.product.func.addr.IAddrOp;
import com.cloudptt.api.product.func.call.CallAttr;
import com.cloudptt.api.product.func.call.CallConst;
import com.cloudptt.api.product.func.call.CallListener;
import com.cloudptt.api.product.func.call.CallTimer;
import com.cloudptt.api.product.func.call.ICallMute;
import com.cloudptt.api.product.func.call.group.GroupCallRecvListener;
import com.cloudptt.api.product.func.call.group.GroupCallTransListener;
import com.cloudptt.api.product.func.call.group.HalfCallInfo;
import com.cloudptt.api.product.func.call.group.GroupCallSpeakListener;
import com.cloudptt.api.product.func.call.group.fsm.floor.FloorAgent;
import com.cloudptt.api.product.func.call.group.fsm.video.IGroupVideoMemberUpdate;
import com.cloudptt.api.product.func.call.group.fsm.video.IVideoSubState;
import com.cloudptt.api.product.func.call.group.fsm.video.GroupCallMemberInfo;
import com.cloudptt.api.product.func.call.group.fsm.video.recv.VideoRecvAgent;
import com.cloudptt.api.product.func.call.group.fsm.video.trans.VideoTransAgent;
import com.cloudptt.api.product.func.call.single.LaunchCallInfo;
import com.cloudptt.api.product.log.Log;
import com.cloudptt.api.product.operator.CallOperator;
import com.cloudptt.api.product.res.Resource;
import com.mcptt.config.model.McIdInfo;
import com.mcptt.db.model.AddrInfo;

import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;

import java.util.Iterator;
import java.util.List;
import java.util.Vector;


public class GroupCallAgent implements ICallState, IVideoSubState,IGroupVideoMemberUpdate
{
	public final static String Log_Key = "GroupCallAgent";
	private ICallState currentState = null;
	private int callMediaState = CallConst.CallMediaState_None;
	private Class<?> cls = null;

	private CallListener listener = null;
	private GroupCallSpeakListener floorListener = null;

	private Context ctx = null;
	private CallAttr callAttr = null;
	private McIdInfo mcIdInfo = null;

	private CallOperator operator = null;
	private IAddrOp addOp = null;
	private CallTimer callTime = null;

	private FloorAgent floorAgent = null;
	private VideoTransAgent videoTransAgent = null;
	private VideoRecvAgent videoRecvAgent = null;

	private RtcpMsg lastRtcpMsg = null;

	private String curCallIdStr = CallAttr.DEF_CALL_ID_STR;
	private String callkey = null;
	private String timeDesc = null;

//	private AlarmTimer keepLiveTimer = null;
//	private volatile boolean isStartTimer = false;
//	public final static String TimerOutKey_Negotiate= "gcall_negotiate";

	private boolean isRecvRelease = false;
	private String groupId = "";
	private String sessionId = "";
	private boolean isSubscribe = false;
	private boolean isShowFloatWin = false;
	private boolean islaunch = true;
	private List<GroupCallMemberInfo> groupCallMemberInfoList = new Vector<GroupCallMemberInfo>();

	public GroupCallAgent(Context ctx,CallAttr callAttr,McIdInfo mcIdInfo,CallOperator operator,IAddrOp addOp)
	{
		Log.d(GroupCallAgent.Log_Key, "CallAgent callAttr = " + callAttr);
		this.ctx = ctx;
		this.callAttr = callAttr;
		this.curCallIdStr = callAttr.getCallIdStr();
		this.callkey = callAttr.getCallKey();
		this.mcIdInfo = mcIdInfo;
//		this.setCur = setCur;
		this.currentState = new InitialState(this);
		this.operator = operator;
		this.addOp = addOp;
		this.callTime = CallTimer.getDefaultCallTimer();
	}

	public void updateCallIdStr(String callIdStr)
	{
		Log.d(GroupCallAgent.Log_Key, "updateCallId callIdStr = " + callIdStr);
		this.curCallIdStr = callIdStr;
		this.callAttr.updateCallIdStr(callIdStr);
		if(floorAgent != null)
		{
			floorAgent.updateCallIdStr(callIdStr);
		}
	}
	public void updateSubcribeInfo(String groupId,String sessionId)
	{
		Log.d(GroupCallAgent.Log_Key, "updateCallId groupId = " + groupId + " sessionId = " + sessionId);
		this.groupId = groupId;
		this.sessionId = sessionId;
	}

	public void setGCallVideoClass(Class cls)
	{
		Log.d(GroupCallAgent.Log_Key, "setGCallVideoClass cls = " + cls);
		this.cls = cls;
	}
	public void setListener(CallListener listener,GroupCallSpeakListener floorListener)
	{
		Log.d(GroupCallAgent.Log_Key, "setListener listener = " + listener.getClass());
		this.listener = listener;
		this.floorListener = floorListener;
		if(floorAgent != null)
		{
			floorAgent.setListener(floorListener);
		}
//		this.videoListener = videoListener;
//		if(videoTransAgent != null)
//		{
//			videoTransAgent.setListener(null);
//		}
	}

	public void setVideoListener(CallListener listener, GroupCallTransListener transListener, GroupCallRecvListener recvListener)
	{
		Log.debug(this.getClass(), "setVideoListener listener = " + listener.getClass()+ ",videoTransAgent =" + ( videoTransAgent != null )
				+ ",videoRecvAgent =" + ( videoRecvAgent != null ));
		this.listener = listener;

		if(videoTransAgent != null)
		{
			videoTransAgent.setListener(transListener);
		}
		if(videoRecvAgent != null)
		{
			videoRecvAgent.setListener(recvListener);
		}
	}

	//	public void setCurGroupInfo(UserInfo curGroupInfo) {
//		this.curGroupInfo = curGroupInfo;
//	}
	public void setIslaunch(boolean islaunch)
	{
		Log.debug(this.getClass(), "setIslaunch islaunch = " + islaunch);
		this.islaunch = islaunch;
	}

	public void goToState(int nextState){
		ICallState callState = null;
		Log.d(GroupCallAgent.Log_Key, "goToState:["+ CallConst.stateTag(this.currentState.getState()) +
				" to "+ CallConst.stateTag(nextState) + "]");

		switch (nextState) {
			case CallConst.CallState_InitState:
				callState = new InitialState(this);
				break;
			case CallConst.CallState_WattingState:
				int seconds = getMakeCallTimer();
				int callDir = callAttr.getCallDir();
				callState = new WattingState(ctx,this,seconds,callDir);
				break;
			case CallConst.CallState_ConnectingState:
				callDir = callAttr.getCallDir();
				callState = new ConnectingState(ctx,this,callDir);
				break;
			case CallConst.CallState_Activite:
				callState = new ActiviteState(this);
				break;
			case CallConst.CallState_DisconnectingState:
				callState = new DisconnectingState(ctx,this);
				break;
			default:
				Log.e(GroupCallAgent.Log_Key, "Illegal state="+ nextState);
				return;//!!!
		}
		this.setCurrentState(callState);
		int callType = callAttr.getCallType();
		boolean isMo = callAttr.isMoCall();
		boolean hasVideo = callAttr.isHasVideo();
		doNextActionBySysState(callState,callType,isMo,hasVideo);
	}

	private void doNextActionBySysState(ICallState callState,int callType,boolean isMo,boolean hasVideo) {
		Log.d(GroupCallAgent.Log_Key, "doNextActionBySysState callState = " + callState + " callType = " + callType + " isMo = " + isMo + " hasVideo = " + hasVideo);
		if (callState.getState() == CallConst.CallState_ConnectingState
				&& CallAttr.isGroupCall(callType)
				&& !isMo
				&& !hasVideo)
		{
			doAcceptAction();
		}
	}

	private int getMakeCallTimer()
	{
		int callType = callAttr.getCallType();
		if(CallAttr.isPrivateCall(callType))
		{
			return 60;
		}
		return 60;
	}

	public void setCurrentState(ICallState currentState)
	{
		this.currentState.destory();
		this.currentState = currentState;
		int callState = currentState.getState();
		if(operator != null) {
			if (CallConst.CallState_ConnectingState != callState)
			{
				operator.ring(ctx,false);
			}
		}

		if(callAttr.isHasVideo()) {
			launchCallActivity(callState, false);
		}
		Log.d( Log_Key, "setCurrentState begin listener = " + listener);
		if(listener != null)
		{
			listener.updateCallState(callkey,callState,false);
		}
		Log.d( Log_Key, "setCurrentState end listener = " + listener);

		if(CallConst.CallState_InitState == callState)
		{
			if(floorAgent != null)
			{
				this.floorAgent.clearResource();
				this.floorAgent = null;
			}

			if(videoTransAgent != null)
			{
				this.videoTransAgent.clearResource();
				this.videoTransAgent = null;
			}

			if(videoRecvAgent != null)
			{
				this.videoRecvAgent.clearResource();
				this.videoRecvAgent = null;
			}

			this.operator.clearResourceForCallEnd(curCallIdStr);
			this.addOp.setCurGroupInfo(null);
//			this.stopTimer();
		}
		else if(CallConst.CallState_Activite == callState)
		{
			int callType = callAttr.getCallType();
			boolean hasVideo = callAttr.isHasVideo();
			if(operator != null) {
				operator.updateAudioChannel(callType,hasVideo);
			}
		}
		else if(CallConst.CallState_DisconnectingState == callState)
		{
			if(operator != null) {
				operator.updateAudioChannel(CallAttr.CallType_Prearranged,false);
			}
		}
	}

	public void initServiveAgentByMcType(boolean isGranted,boolean hasVideo)
	{
		Log.d( Log_Key, "initServiveAgentByMcType isGranted = " + isGranted);
		if(!hasVideo
				&& floorAgent == null)
		{
			initFloorAgent(isGranted,lastRtcpMsg);
		}
		else if(hasVideo
				&& videoTransAgent == null)
		{
			if(videoTransAgent == null) {
				initVideoTransAgent(isGranted, lastRtcpMsg);
			}
			if(videoRecvAgent == null) {
				initVideoRecvAgent(isGranted, lastRtcpMsg);
			}
		}

		lastRtcpMsg = null;
	}

	protected void initFloorAgent(boolean isGranted,RtcpMsg lastRtcpMsg)
	{
		Log.d( Log_Key, "initFloorAgent isGranted = " + isGranted + " lastRtcpMsg = " + lastRtcpMsg);
//		if(floorAgent != null)
//		{
//			floorAgent.clearResource();
//			floorAgent = null;
//		}
		String callKey = this.callAttr.getCallKey();
		floorAgent = new FloorAgent(this.ctx,curCallIdStr,callKey,operator,addOp,callTime);
//		floorAgent.setFloorInfo(callAttr,mcIdInfo);
		floorAgent.setListener(floorListener);
		if(isGranted)
		{
			floorAgent.goToState(CallConst.FloorState_Permission,null);
		}
		if(lastRtcpMsg != null)
		{
			floorAgent.receiveRtcpMsg(lastRtcpMsg);
		}
		Log.d( Log_Key, "initFloorAgent end");
	}

	protected void initVideoTransAgent(boolean isGranted,RtcpMsg lastRtcpMsg)
	{
		Log.d( Log_Key, "initVideoTransAgent isGranted = " + isGranted + "lastRtcpMsg = " + lastRtcpMsg);
		videoTransAgent = new VideoTransAgent(this.ctx, callkey,curCallIdStr,operator,addOp,callTime,this);
		videoTransAgent.setListener(null);
		if(isGranted)
		{
			videoTransAgent.goToState(CallConst.VideoTransState_Permission);
		}

		if(lastRtcpMsg != null)
		{
			boolean isVideoTransRtcpMsg = lastRtcpMsg.isVideoTransRtcpMsg();
			Log.d( Log_Key, "initVideoTransAgent isVideoTransRtcpMsg = " + isVideoTransRtcpMsg);
			if(isVideoTransRtcpMsg) {
				videoTransAgent.receiveRtcpMsg(lastRtcpMsg);
			}
		}
	}
	protected void initVideoRecvAgent(boolean isGranted,RtcpMsg lastRtcpMsg)
	{
		Log.d( Log_Key, "initVideoRecvAgent isGranted = " + isGranted + "lastRtcpMsg = " + lastRtcpMsg);
		videoRecvAgent = new VideoRecvAgent(this.ctx, callkey,curCallIdStr,operator,addOp,callTime,this);
		videoRecvAgent.setListener(null);
		if(isGranted)
		{
			videoRecvAgent.goToState(CallConst.VideoRecvState_Permission);
		}

		if(lastRtcpMsg != null)
		{
			boolean isVideoRecvRtcpMsg = lastRtcpMsg.isVideoRecvRtcpMsg();
			Log.d( Log_Key, "initVideoRecvAgent isVideoRecvRtcpMsg = " + isVideoRecvRtcpMsg);
			if(isVideoRecvRtcpMsg) {
				videoRecvAgent.receiveRtcpMsg(lastRtcpMsg);
			}
		}
	}

	//	private boolean cachedVideo = false;
//	public void onDisplayVideo(int callId, boolean show)
//	{
//		Log.d( Log_Key, GroupCallConst.stateTag(this.currentState.getState()) +" cachedVideo=" + cachedVideo + ",show=" + show );
//		cachedVideo = show ;
//		if( listener != null ) 
//		{
//			
//			listener.onDisplayVideo( callId, show );
//		}
////		if( !cachedVideo ) {
////			if( speakAgent != null
////					&& GroupCallConst.FloorState_NoPermission == speakAgent
////					.getCurrentState( ) ) {
//////				initServiceAgent( );
////			}
////		}
//	}
	public int doUserAction(int btnAction)
	{
		return CauseCont.OperateErr_NoAgent;
	}

	public int doUserAction(int btnAction,String jsonStr)
	{
		Log.d( GroupCallAgent.Log_Key,
				"callkey = " + callkey + " " + CallConst.stateTag(this.currentState.getState()) + " doUserAction = " + CallConst.userActionTag( btnAction )
						+ ",jsonStr =" + jsonStr
						+ ",floorAgent=" + ( floorAgent != null )
						+ ",videoTransAgent =" + ( videoTransAgent != null )
						+ ",videoRecvAgent =" + ( videoRecvAgent != null ));
		if(isRecvRelease)
		{
			int result = CauseCont.OperateErr_OpQuick;//floorAgent.do UserAction( btnAction );
			Log.d(GroupCallAgent.Log_Key, "doBtnAction btnAction = " + btnAction +  " result = " + result + " isRecvRelease = " + isRecvRelease);
		}
		if(CallConst.BtnAction_Request == btnAction
				|| btnAction == CallConst.BtnAction_Hangup)
		{
			mHandler.removeMessages(MsgId_Release);
		}
		int result = CauseCont.OperateErr_NoAgent;
		if(videoTransAgent != null
				&& (btnAction == CallConst.BtnAction_Trans_Begin
				|| btnAction == CallConst.BtnAction_Trans_End))
		{
			result = videoTransAgent.doUserAction( btnAction ,jsonStr);
			Log.d(GroupCallAgent.Log_Key, "videoTransAgent.doBtnAction btnAction = " + btnAction +  " result = " + result);
		}
		else if(videoRecvAgent != null
				&& (btnAction == CallConst.BtnAction_Recv_Begin
				|| btnAction == CallConst.BtnAction_Recv_End))
		{
			result = videoRecvAgent.doUserAction( btnAction,jsonStr );
			Log.d(GroupCallAgent.Log_Key, "videoRecvAgent.doBtnAction btnAction = " + btnAction +  " result = " + result);
		}
		else if( floorAgent != null
				&& (btnAction == CallConst.BtnAction_Request
				|| btnAction == CallConst.BtnAction_Release ))
		{
			result = floorAgent.doUserAction( btnAction );
			Log.d(GroupCallAgent.Log_Key, "floorAgent.doBtnAction btnAction = " + btnAction +  " result = " + result);
		}
		else if( floorAgent == null
				&& btnAction == CallConst.BtnAction_Release)
		{
			isRecvRelease = true;
			result = CauseCont.OperateCheck_Suc;//floorAgent.do UserAction( btnAction );
			Log.d(GroupCallAgent.Log_Key, "floorAgent == null speakAgent.doBtnAction btnAction = " + btnAction +  " result = " + result);
			Message msg = mHandler.obtainMessage(MsgId_Release);
			mHandler.sendMessageDelayed(msg, 1000);
		}
		else
		{
			result =  currentState.doUserAction( btnAction );
			Log.d(GroupCallAgent.Log_Key, "callAgent.doBtnAction btnAction is " + btnAction +  " result is " + result);
		}
		return result;
	}

	public boolean isActiveCall()
	{
		//		if( operator!=null)
		//		{
		//			return operator.isActiveCall();
		//		}
		int talkState = currentState.getState();
		Log.d(GroupCallAgent.Log_Key, "isActiveCall talkState = " + talkState);
		if(CallConst.CallState_InitState != talkState)
		{
			return true;
		}
		return false;
	}

	public boolean setMicrophoneEnable(boolean enable)
	{
		Log.debug(this.getClass(),"setMicrophoneEnable enable = " + enable);
		Context ctx = this.getCtx();
		CallOperator operator = this.getOperator();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return false;
		}

		return operator.setMicrophoneEnable(curCallIdStr, enable);
	}
	public void receiveCallAction(int callAction)
	{
		Log.debug( this.getClass(),
				CallConst.stateTag(this.currentState.getState()) + " receiveCallAction callAction = "
						+ CallConst.sessionTag( callAction ) );

		currentState.receiveCallAction( callAction );
	}
	public void receiveCallMediaStatus(int mediaStatus)
	{
		Log.debug(this.getClass(),
				CallConst.stateTag(this.currentState.getState()) + " receivePCallMediaStatus mediaStatus = "
						+ mediaStatus);
		this.callMediaState = mediaStatus;
		if(listener != null)
		{
			listener.updateMediaStatus(callkey,mediaStatus);
		}
	}
	public void receivePCallVideoEvent()
	{
		Log.debug(this.getClass(),
				CallConst.stateTag(this.currentState.getState()) + " receivePCallVideoEvent");
		if(listener != null)
		{
			listener.updateVideoEvent(callkey);
		}
	}
	public void receiveRtcpMsg(RtcpMsg msg)
	{
		Log.d(GroupCallAgent.Log_Key, CallConst.stateTag(this.currentState.getState()) + " receiveSpeakInfo RtcpMsg = " + msg);
		if(msg == null)
		{
			return;
		}
		if(!callAttr.isHasVideo())
		{
			operator.setSpeakerphoneEnable(true);
		}
		if(floorAgent == null
			&& videoTransAgent == null
			&& videoRecvAgent == null)
		{
			lastRtcpMsg = msg;
			Log.d(GroupCallAgent.Log_Key, "receiveRtcpMsg speakAgent videoTransAgent videoRecvAgent = null");
		}
		if(!msg.isVideoRtcpMsg())
		{
			if(floorAgent != null)
			{
				this.floorAgent.receiveRtcpMsg(msg);
			}
		}
		else
		{
			boolean isVideoTransRtcpMsg = msg.isVideoTransRtcpMsg();
			boolean isVideoRecvRtcpMsg = msg.isVideoRecvRtcpMsg();
			Log.d(GroupCallAgent.Log_Key, "receiveRtcpMsg isVideoTransRtcpMsg = " + isVideoTransRtcpMsg + " isVideoRecvRtcpMsg = " + isVideoRecvRtcpMsg);
			if(isVideoTransRtcpMsg
				&& videoTransAgent != null)
			{
				this.videoTransAgent.receiveRtcpMsg(msg);
			}
			if(videoRecvAgent != null
					&& isVideoRecvRtcpMsg)
			{
				this.videoRecvAgent.receiveRtcpMsg(msg);
			}
		}
	}
	public void updateTakenUser(AddrInfo user)
	{}

	public int getState()
	{
		return this.currentState.getState();
	}

	public HalfCallInfo getCallInfo()
	{
		Log.d(GroupCallAgent.Log_Key, "getCallInfo");
		int callState = currentState.getState();
		int mediaState = this.callMediaState;
		boolean hasVideo = callAttr.isHasVideo();
		int speakState = CallConst.FloorState_Null;
		AddrInfo floorUserInfo = null;
		if(floorAgent != null)
		{
			speakState = floorAgent.getState();
			floorUserInfo = floorAgent.getFloorUserInfo();
		}
		int transState = CallConst.VideoTransState_Begin;
		if( videoTransAgent != null){
			transState = videoTransAgent.getState();
		}
		int recvState = CallConst.VideoTransState_Begin;
		if( videoRecvAgent != null){
			recvState = videoRecvAgent.getState();
		}
		return new HalfCallInfo(callAttr,callState,mediaState,hasVideo,speakState,floorUserInfo, transState,recvState,groupCallMemberInfoList);
	}

	public void rollback()
	{
		Log.d(GroupCallAgent.Log_Key, "IdleState rollbackState");
		if( !callAttr.isHasVideo() )
		{
			this.currentState.doUserAction(CallConst.BtnAction_Hangup);
		}
	}

	public void updateTimer(CallTimer time) {
		this.callTime.updateTime(time);
		if(floorAgent != null)
		{
			this.floorAgent.updateTime(time);
		}
		if(videoTransAgent != null)
		{
			this.videoTransAgent.updateTime(time);
		}
	}


	@Override
	public void destory() {
		// TODO Auto-generated method stub
		if(this.operator != null)
		{
			this.operator.hangupCall(curCallIdStr, 486);
			this.operator.clearResourceForCallEnd(curCallIdStr);
		}
		if(mHandler != null)
		{
			mHandler.removeMessages(MsgId_Release);
		}
		if(floorAgent != null)
		{
			floorAgent.destory();
		}
		if(videoRecvAgent != null)
		{
			videoRecvAgent.destory();
		}
		if(videoTransAgent != null)
		{
			videoTransAgent.destory();
		}
		mHandler = null;
		timeDesc = null;
		if(currentState != null)
		{
			this.currentState.destory();
		}
//		this.stopTimer();
	}

//	public void incomingCall(AddrInfo incomingInfo)
//	{
//		Log.d(GroupCallAgent.Log_Key, "incomingCall callkey = " + callkey + "incomingCall incomingInfo = " + incomingInfo);
//		this.goToState(CallConst.CallState_ConnectingState);
////		if(callAttr != null
////			&& callAttr.isHasVideo())
////		{
////			goToState(CallConst.Session_Connecting);
////		}
////		else {
////			if (this.listener != null) {
////				this.listener.incomingCall(callkey, incomingInfo);
////			}
////		}
//	}

	protected int doMakeCallAction()
	{
		Context ctx = this.getCtx();
//		boolean isVideo = false;
//		int callType = CallAttr.CallType_Group;
		Log.d(GroupCallAgent.Log_Key, "doMakeCallAction callAttr = " + callAttr);
		if(callAttr == null)
		{
			return CauseCont.OperateErr_Exception;
		}
		CallOperator operator = this.getOperator();
		if(null == operator
				|| null == ctx)
		{
			Log.d(GroupCallAgent.Log_Key, "doMakeCallAction operator_null");
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}
//		if(curGroupInfo == null)
//		{
//			String errStr =  Resource.getString("group_null");//this.agent.getCtx().getString(R.string.group_null);
//			CommDlg.showToast(ctx,errStr);
//			return CauseCont.OperateErr_GroupNull;
//		}
//		Log.e(CallAgent.Log_Key, "doBtnDownAction BtnId_Talk_Down curGroupInfo is " + curGroupInfo);
		int callType = callAttr.getCallType();
		String groupNum = callAttr.getGroupInfo().getAddrId();//.getGroupNum();
//		String curNum = mcIdInfo.getMcId();
//		if(isVideo)
//		{
//			callee = callAttr.getCalled().getMcvideoId();
//			curNum = mcIdInfo.getMcvideoId();
//			mcType = UserInfo.McType_Video;
//		}

//		int result = operator.makeCall(SipCallSession.Call_Group,1,curNum, 
//				agent.getOperator( ).getConfig( ).isVideoEnable( ) );
		boolean hasVidoe = callAttr.isHasVideo();
		boolean isEmergency = callAttr.isEmergency();
		String funcNum = callAttr.getFuncName();
		String locationStr = callAttr.getLocationStr();

		int result = operator.makeCall(callType,groupNum,hasVidoe,isEmergency,funcNum,locationStr);
		if(result != CauseCont.OperateCheck_Suc)
		{
			String errStr = CauseCont.getOperateCheckErrStr(result,ctx);
			CommDlg.showToast(ctx,errStr);
			return result;
		}
		return CauseCont.OperateCheck_Suc;
	}

	public int doAcceptAction()
	{
		Log.e(GroupCallAgent.Log_Key,"doAcceptAction");
		Context ctx = this.getCtx();
		CallOperator operator = this.getOperator();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}

		int result = operator.answerCall(curCallIdStr, callAttr.isHasVideo());//.hangupCall(curCallId,486);
		if(result != CauseCont.OperateCheck_Suc)
		{
			String errStr = CauseCont.getOperateCheckErrStr(result,ctx);
			CommDlg.showToast(ctx,errStr);
			return result;
		}
		return CauseCont.OperateCheck_Suc;
	}

	protected int doHangupAction(int code)
	{
		Log.e(GroupCallAgent.Log_Key,"doHangupAction");
		Context ctx = this.getCtx();
		CallOperator operator = this.getOperator();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}

		int result = operator.hangupCall(curCallIdStr,code);
		if(result != CauseCont.OperateCheck_Suc)
		{
			String errStr = CauseCont.getOperateCheckErrStr(result,ctx);
			CommDlg.showToast(ctx,errStr);
			return result;
		}
		return CauseCont.OperateCheck_Suc;
	}

	public int doSubscribe()
	{
		Log.e(GroupCallAgent.Log_Key,"doSubscribe");
		Context ctx = this.getCtx();
		CallOperator operator = this.getOperator();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}
		String called =  callAttr.getCalled().getAddrId();
		String uri = AddrInfo.toSipUrlFromNum(called);
		operator.sendSubscribe(uri);
		return CauseCont.OperateCheck_Suc;
	}

	public int doSwitchCamera()
	{
		Log.e(GroupCallAgent.Log_Key,"doSwitchCamera");
		Context ctx = this.getCtx();
		CallOperator operator = this.getOperator();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}
		String called =  callAttr.getCalled().getAddrId();
		String uri = AddrInfo.toSipUrlFromNum(called);
		operator.switchCamera(curCallIdStr);
		return CauseCont.OperateCheck_Suc;
	}

	public int ring()
	{
		Log.e(GroupCallAgent.Log_Key,"ring");
		Context ctx = this.getCtx();
		CallOperator operator = this.getOperator();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}

		operator.ring(ctx,true);
		return CauseCont.OperateCheck_Suc;
	}
	protected int floorRelease()
	{
		Log.d(GroupCallAgent.Log_Key, "floorRelease");
		Context ctx = this.getCtx();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}

		int result = operator.sendFloorMsg(curCallIdStr,CallAttr.RtcpMsg_Release);
		if(result != CauseCont.OperateCheck_Suc)
		{
			String errStr = CauseCont.getOperateCheckErrStr(result,ctx);
			CommDlg.showToast(ctx,errStr);
			return result;
		}
		return CauseCont.OperateCheck_Suc;
	}

	public int subcribeConference(boolean isActivit)
	{
		Log.d(GroupCallAgent.Log_Key, "subcribeConference isActivit = " + isActivit + " sessionId = " + sessionId + " groupId = " + groupId + " isSubscribe = " + isSubscribe);
		if(!isActivit
				&& !isSubscribe)
		{
			Log.d(GroupCallAgent.Log_Key, "subcribeConference no subcribeConference");
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}
		else if(isActivit
				&& isSubscribe)
		{
			Log.d(GroupCallAgent.Log_Key, "subcribeConference subcribeConference running");
			return CauseCont.OperateErr_Invalid;
		}

		Context ctx = this.getCtx();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return CauseCont.OperateCheck_Sys_UserKeyNull;
		}
		String groupIdUrl = AddrInfo.toUrlFromNum(groupId);
		boolean hasVideo = callAttr.isHasVideo();
		operator.subcribeConference(curCallIdStr,isActivit,sessionId,groupIdUrl, hasVideo);
		isSubscribe = isActivit;
		return CauseCont.OperateCheck_Suc;
	}

//	public void startTimer() {
//		Log.d(SingleCallAgent.Log_Key, "startTimer");
//
//		stopTimer();
//		this.keepLiveTimer = new AlarmTimer(ctx,TimerOutKey_Negotiate,5,this);
//		keepLiveTimer.startRefreshTimer();
//	}
//
//	public void stopTimer() {
//		Log.d(SingleCallAgent.Log_Key, "stopTimer");
//		if(keepLiveTimer != null)
//		{
//			this.keepLiveTimer.stopRefreshTimer();
//			this.keepLiveTimer = null;
//		}
//		isStartTimer = false;
//	}

//	@Override
//	public void timeIntervalTimeout(String alarmAction) {
//		// TODO Auto-generated method stub
//		Log.d(SingleCallAgent.Log_Key, "timeIntervalTimeout alarmAction = " + alarmAction);
//		if(TimerOutKey_Negotiate.equals(alarmAction))
//		{
//			this.operator.negotiateRtpChannel(curCallIdStr);
//		}
//
//	}

//	public int negotiateRtpChannel()
//	{
//		Log.d(GroupCallAgent.Log_Key, "negotiateRtpChannel");
//		Context ctx = this.getCtx();
//		if(null == operator
//				|| null == ctx)
//		{
//			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
//			CommDlg.showToast(ctx,errStr);
//			return CauseCont.OperateCheck_Sys_UserKeyNull;
//		}
//
//		int result = operator.negotiateRtpChannel(curCallIdStr);
//		if(result != CauseCont.OperateCheck_Suc)
//		{
//			String errStr = CauseCont.getOperateCheckErrStr(result,ctx);
//			CommDlg.showToast(ctx,errStr);
//			return result;
//		}
//		return CauseCont.OperateCheck_Suc;
//	}
//	protected int doExitAction()
//	{
//		Context ctx = this.getCtx();
//		CallOperator operator = this.getOperator();
//		if(null == operator
//				|| null == ctx)
//		{
//			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
//			CommDlg.showToast(ctx,errStr);
//			return CauseCont.OperateCheck_Sys_UserKeyNull;
//		}
//		
//		int result = operator.hangupCall(SipCallSession.Call_Group);
//		if(result != CauseCont.OperateCheck_Suc) 
//		{
//			String errStr = CauseCont.getOperateCheckErrStr(result,ctx);
//			CommDlg.showToast(ctx,errStr);
//			return result;
//		}
//		return CauseCont.OperateCheck_Suc;
//	}

	public void destoryCall()
	{
		Log.d(GroupCallAgent.Log_Key, "destoryCall");
		Context ctx = this.getCtx();
		CallOperator operator = this.getOperator();
		if(null == operator
				|| null == ctx)
		{
			String errStr =  Resource.getString("operator_null");//ctx.getString(R.string.operator_null);
			CommDlg.showToast(ctx,errStr);
			return;
		}
		operator.destoryCall(curCallIdStr);
	}

	public Context getCtx() {
		return ctx;
	}

	public CallOperator getOperator() {
		return operator;
	}

	public void clearGroupCall()
	{
		Log.d(GroupCallAgent.Log_Key,"clearGroupCall");
		int result = operator.hangupCall(curCallIdStr,0);
		if(result != CauseCont.OperateCheck_Suc)
		{
			String errStr = CauseCont.getOperateCheckErrStr(result,ctx);
			CommDlg.showToast(ctx,errStr);
			return;
		}
	}

	public CallListener getListener() {
		return listener;
	}

	public String getCurCallIdStr() {
		return curCallIdStr;
	}
	public String getCallkey() {
		return callkey;
	}

	public void updateCallDuration(int sec)
	{
		this.timeDesc = Common.getTime(sec);
		if(this.listener != null)
		{
			listener.updateCallDuration(callkey, ""+ timeDesc);
		}
	}

	public CallAttr getCallAttr() {
		return callAttr;
	}
	public String getTimeDesc() {
		Log.d(GroupCallAgent.Log_Key, "getTimeDesc timeDesc = " + timeDesc);
		return timeDesc;
	}

	private final static int MsgId_Release = 1;
	private  Handler mHandler = new Handler(){
		@Override
		public void handleMessage(Message msg)
		{
			if(msg.what == MsgId_Release)
			{
				Log.d(GroupCallAgent.Log_Key, "mHandler MsgId_Release");
//
				if(floorAgent != null)
				{
					int result = floorAgent.doUserAction(CallConst.BtnAction_Release);
					if(CauseCont.OperateErr_Invalid == result)
					{
						Log.d(GroupCallAgent.Log_Key, "mHandler MsgId_Release OperateErr_Invalid");
						Message newMsg = mHandler.obtainMessage(MsgId_Release);
						mHandler.sendMessageDelayed(newMsg, 500);
					}
					isRecvRelease = false;
				}
				else
				{
					Log.d(GroupCallAgent.Log_Key, "mHandler MsgId_Release floorAgent == null");
					Message newMsg = mHandler.obtainMessage(MsgId_Release);
					mHandler.sendMessageDelayed(newMsg, 1000);
				}


			}
		}
	};

//	@Override
//	public void muteCall(boolean isOn) {
//		// TODO Auto-generated method stub
//		operator.muteCall(curCallIdStr, isOn);//.holdGroupCall(curCallId);
//	}

	private void launchCallActivity(int callState,boolean isFirst)
	{
		Log.debug(this.getClass(), "launchCallActivity isShowFloatWin = " + isShowFloatWin + " callState = " + callState);
		if(callAttr.getCallDir() == CallAttr.CallDir_MT && callState == CallConst.CallState_WattingState)
		{
			return;
		}
		if(isShowFloatWin)
		{
			return;
		}
		Log.debug(this.getClass(), "launchCallActivity callState = " + callState + " isFirst = " + isFirst);
		boolean isLaunch = isLaunch(callState,isFirst);
		Log.debug(this.getClass(), "launchCallActivity isLaunch = " + isLaunch);
		if(isLaunch)
		{
			AddrInfo info = callAttr.getGroupInfo();
//			boolean isDac = mcIdInfo.isDac();
			LaunchCallInfo callInfo = callAttr.toLaunchCallInfo(false, callState, callMediaState,isLaunch);
			launchCallActivity(callInfo,info);
		}
	}

	private boolean isLaunch(int callState,boolean isFirst)
	{
		if(CallConst.CallState_InitState == callState
				&& isFirst)
		{
			return true;
		}
		else if(CallConst.CallState_Activite >= callState
				&& CallConst.CallState_InitState != callState)
		{
			return true;
		}
		return false;
	}
	private void launchCallActivity(LaunchCallInfo callInfo, AddrInfo userInfo)
	{
		Log.debug(this.getClass(), "launchCallActivity callInfo = " + callInfo);
		Log.debug(this.getClass(), "launchCallHandler userInfo = " + userInfo);
		if(cls == null)
		{
			doHangupAction(406);
			return;
		}
		Log.debug(this.getClass(), "launchCallHandler islaunch = " + islaunch);
		if(!islaunch)
		{
			return;
		}
		Intent intent = new Intent(this.ctx,cls);
		intent.putExtra(SipManager.EXTRA_PRIVACY_CALL_INFO, callInfo);
		intent.putExtra(SipManager.EXTRA_PRIVACY_CALL_USER, userInfo);
		intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

		this.ctx.startActivity(intent);
		//		showNotificationForCall(talkState,userInfo);
	}

	@Override
	public void updateGroupCallMemberInfo(int type,GroupCallMemberInfo info)
	{
		Log.debug(this.getClass(), "updateGroupCallMemberInfo type = " + type + " updateGroupCallMemberInfo info = " + info + " groupCallMemberInfoList = "  + groupCallMemberInfoList);
		if(info != null
				&& info.getGroupMembInfo() != null
				&& groupCallMemberInfoList != null)
		{
			boolean isHas = false;
			for (Iterator<GroupCallMemberInfo> itor = groupCallMemberInfoList.iterator(); itor.hasNext();)
			{
				GroupCallMemberInfo ob = itor.next();
				if(ob != null
						&& ob.isSameOne(info))
				{
//					groupCallMemberInfoList.remove(ob);
					isHas = true;
					if(type == IGroupVideoMemberUpdate.Type_Trans)
					{
						ob.updateTrans(info.isTrans());
					}
					else if(type == IGroupVideoMemberUpdate.Type_Recv)
					{
						ob.updateRecv(info.isRecv());
					}
					Log.debug(this.getClass(), "updateGroupCallMemberInfo ob = " + ob );
					if(!ob.isTrans()
							&& !ob.isRecv())
					{
						itor.remove();
					}
				}
			}
			if(!isHas) {
				String mcId = mcIdInfo.getAddrId();
				if(!info.isSameOne(mcId)
				&&(info.isTrans()||info.isRecv())) {
					groupCallMemberInfoList.add(info);
				}
			}
			Log.debug(this.getClass(), "updateGroupCallMemberInfo after groupCallMemberInfoList = " + groupCallMemberInfoList);
			if(listener != null)
			{
				listener.updateGroupCallMemberInfoList(groupCallMemberInfoList);
			}
			else
			{
				Log.debug(this.getClass(), "updateGroupCallMemberInfo listener = null");
			}

		}
	}
	@Override
	public void clearGroupCallMemberRecvState(GroupCallMemberInfo info)
	{
		Log.debug(this.getClass(), "clearGroupCallMemberRecvState info = "  + info + " groupCallMemberInfoList = "  + groupCallMemberInfoList);
		if(groupCallMemberInfoList != null)
		{
			for (Iterator<GroupCallMemberInfo> itor = groupCallMemberInfoList.iterator(); itor.hasNext();)
			{
				GroupCallMemberInfo ob = itor.next();
				if(ob != null && ob.isSameOne(info))
				{
					ob.updateRecv(false);
					if(!ob.isTrans()
							&& !ob.isRecv())
					{
						itor.remove();
					}
				}
			}
			Log.debug(this.getClass(), "clearGroupCallMemberRecvState after groupCallMemberInfoList = " + groupCallMemberInfoList);
			if(listener != null)
			{
				listener.updateGroupCallMemberInfoList(groupCallMemberInfoList);
			}

		}
	}
	@Override
	public void clearGroupCallMemberRecvState()
	{
		Log.debug(this.getClass(), "clearGroupCallMemberRecvState groupCallMemberInfoList = "  + groupCallMemberInfoList);
		if(groupCallMemberInfoList != null)
		{
			for (Iterator<GroupCallMemberInfo> itor = groupCallMemberInfoList.iterator(); itor.hasNext();)
			{
				GroupCallMemberInfo ob = itor.next();
				if(ob != null)
				{
					ob.updateRecv(false);
					if(!ob.isTrans()
							&& !ob.isRecv())
					{
						itor.remove();
					}
				}
			}
			Log.debug(this.getClass(), "clearGroupCallMemberRecvState after groupCallMemberInfoList = " + groupCallMemberInfoList);
			if(listener != null)
			{
				listener.updateGroupCallMemberInfoList(groupCallMemberInfoList);
			}

		}
	}

}
